package club.lemos.heartbeat

import android.Manifest
import android.annotation.SuppressLint
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCharacteristic
import android.bluetooth.BluetoothGattServer
import android.bluetooth.BluetoothGattServerCallback
import android.bluetooth.BluetoothGattService
import android.bluetooth.BluetoothManager
import android.bluetooth.BluetoothProfile
import android.bluetooth.le.AdvertiseCallback
import android.bluetooth.le.AdvertiseData
import android.bluetooth.le.AdvertiseSettings
import android.bluetooth.le.BluetoothLeAdvertiser
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.os.ParcelUuid
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat
import java.util.Timer
import java.util.UUID
import kotlin.concurrent.timerTask

class MainActivity : ComponentActivity() {

    private lateinit var bluetoothManager: BluetoothManager
    private lateinit var bluetoothAdapter: BluetoothAdapter
    private var bluetoothLeAdvertiser: BluetoothLeAdvertiser? = null
    private var gattServer: BluetoothGattServer? = null
    private var timer: Timer? = null

    // UUID 定义
    private val CURRENT_TIME_SERVICE_UUID: UUID =
        UUID.fromString("00001805-0000-1000-8000-00805f9b34fb")
    private val CURRENT_TIME_CHAR_UUID: UUID =
        UUID.fromString("00002a2b-0000-1000-8000-00805f9b34fb")

    // 用于记录已连接设备（同时作为 Compose 状态使用）
    private val connectedDevicesState = mutableStateListOf<BluetoothDevice>()

    private val gattServerCallback = object : BluetoothGattServerCallback() {
        override fun onConnectionStateChange(device: BluetoothDevice, status: Int, newState: Int) {
            // 在主线程更新状态，确保 Compose 可观察
            runOnUiThread {
                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    if (!connectedDevicesState.contains(device)) {
                        connectedDevicesState.add(device)
                    }
                } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    connectedDevicesState.remove(device)
                }
            }
        }

        @SuppressLint("MissingPermission")
        override fun onCharacteristicReadRequest(
            device: BluetoothDevice,
            requestId: Int,
            offset: Int,
            characteristic: BluetoothGattCharacteristic
        ) {
            if (!hasAllPermissions()) return
            if (characteristic.uuid == CURRENT_TIME_CHAR_UUID) {
                //被动响应
                val currentTime = "Read:" + System.currentTimeMillis().toString()
                gattServer?.sendResponse(
                    device,
                    requestId,
                    BluetoothGatt.GATT_SUCCESS,
                    0,
                    currentTime.toByteArray()
                )
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        bluetoothManager = getSystemService(BLUETOOTH_SERVICE) as BluetoothManager
        bluetoothAdapter = bluetoothManager.adapter

        bluetoothLeAdvertiser = bluetoothAdapter.bluetoothLeAdvertiser

        requestPermissionsIfNeeded()

        setContent {
            BLEPeripheralScreen()
        }
    }

    @SuppressLint("MissingPermission")
    override fun onDestroy() {
        super.onDestroy()
        stopHeartbeat()
        stopAdvertising()
        if (!hasAllPermissions()) return
        gattServer?.close()
    }

    // Permission handling using Activity Result API
    @SuppressLint("MissingPermission")
    private val requestPermissionLauncher = registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { permissions ->
        val allGranted = permissions.all { it.value }
        if (allGranted) {
            startGattServer()
            startAdvertising()
            startHeartbeat()
        }
    }

    private fun requestPermissionsIfNeeded() {
        val permissions = mutableListOf(
            Manifest.permission.BLUETOOTH,
            Manifest.permission.BLUETOOTH_ADMIN
        )
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            permissions.add(Manifest.permission.BLUETOOTH_ADVERTISE)
            permissions.add(Manifest.permission.BLUETOOTH_CONNECT)
        } else {
            permissions.add(Manifest.permission.ACCESS_FINE_LOCATION)
        }

        val notGranted = permissions.filter {
            ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED
        }

        if (notGranted.isNotEmpty()) {
            requestPermissionLauncher.launch(notGranted.toTypedArray())
        }
    }

    private fun hasAllPermissions(): Boolean {
        val permissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            listOf(
                Manifest.permission.BLUETOOTH_ADVERTISE,
                Manifest.permission.BLUETOOTH_CONNECT
            )
        } else {
            listOf(Manifest.permission.ACCESS_FINE_LOCATION)
        }

        return permissions.all {
            ContextCompat.checkSelfPermission(this, it) == PackageManager.PERMISSION_GRANTED
        }
    }

    @SuppressLint("MissingPermission")
    private fun startGattServer() {
        if (!hasAllPermissions()) return

        gattServer = bluetoothManager.openGattServer(this, gattServerCallback)
        val service = BluetoothGattService(
            CURRENT_TIME_SERVICE_UUID,
            BluetoothGattService.SERVICE_TYPE_PRIMARY
        )
        val characteristic = BluetoothGattCharacteristic(
            CURRENT_TIME_CHAR_UUID,
            BluetoothGattCharacteristic.PROPERTY_READ
                    or BluetoothGattCharacteristic.PROPERTY_NOTIFY,
            BluetoothGattCharacteristic.PERMISSION_READ
        )
        service.addCharacteristic(characteristic)
        gattServer?.addService(service)
    }

    @SuppressLint("MissingPermission")
    private fun startAdvertising() {
        if (!hasAllPermissions()) return
        // 自定义设备名称（广播中显示的名称）
        bluetoothAdapter.name = "Custom BLE Heartbeat"
        val settings = AdvertiseSettings.Builder()
            .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
            .setConnectable(true)
            .setTimeout(0)
            .build()

        val data = AdvertiseData.Builder()
            .setIncludeDeviceName(true) // 广告数据中包含设备名称
            .addServiceUuid(ParcelUuid(CURRENT_TIME_SERVICE_UUID))
            .build()

        bluetoothLeAdvertiser?.startAdvertising(settings, data, advertiseCallback)
    }

    @SuppressLint("MissingPermission")
    private fun stopAdvertising() {
        if (!hasAllPermissions()) return
        bluetoothLeAdvertiser?.stopAdvertising(advertiseCallback)
    }

    private val advertiseCallback = object : AdvertiseCallback() {
        override fun onStartSuccess(settingsInEffect: AdvertiseSettings) {}
        override fun onStartFailure(errorCode: Int) {}
    }

    private fun startHeartbeat() {
        timer = Timer()
        timer?.schedule(timerTask {
            sendCurrentTimeNotification()
        }, 0, 1000)
    }

    private fun stopHeartbeat() {
        timer?.cancel()
        timer = null
    }

    @SuppressLint("MissingPermission")
    private fun sendCurrentTimeNotification() {
        //主动通知
        val currentTime = "Push:" + System.currentTimeMillis().toString()
        val service = gattServer?.getService(CURRENT_TIME_SERVICE_UUID)
        val characteristic = service?.getCharacteristic(CURRENT_TIME_CHAR_UUID)
        characteristic?.value = currentTime.toByteArray()

        // 通知所有已连接的设备
        connectedDevicesState.forEach { device ->
            if (!hasAllPermissions()) return
            gattServer?.notifyCharacteristicChanged(device, characteristic, false)
        }
    }

    @Composable
    fun BLEPeripheralScreen() {
        var isAdvertising by remember { mutableStateOf(false) }

        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(16.dp),
            verticalArrangement = Arrangement.Top,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text(
                "BLE Peripheral - Heartbeat Service",
                style = MaterialTheme.typography.headlineMedium
            )
            Spacer(modifier = Modifier.height(16.dp))

            Button(onClick = {
                if (isAdvertising) {
                    stopAdvertising()
                    stopHeartbeat()
                } else {
                    if (hasAllPermissions()) {
                        startGattServer()
                        startAdvertising()
                        startHeartbeat()
                    } else {
                        requestPermissionsIfNeeded()
                    }
                }
                isAdvertising = !isAdvertising
            }) {
                Text(if (isAdvertising) "Stop Advertising" else "Start Advertising")
            }

            Spacer(modifier = Modifier.height(16.dp))
            Text("Status: ${if (isAdvertising) "Advertising" else "Not Advertising"}")

            Spacer(modifier = Modifier.height(24.dp))
            Text("Connected Devices:", style = MaterialTheme.typography.headlineSmall)
            Spacer(modifier = Modifier.height(8.dp))

            // 使用 LazyColumn 显示已连接设备列表
            if (connectedDevicesState.isEmpty()) {
                Text("No connected devices")
            } else {
                LazyColumn(modifier = Modifier.fillMaxWidth()) {
                    items(connectedDevicesState) { device ->
                        DeviceItem(device)
                    }
                }
            }
        }
    }

    @SuppressLint("MissingPermission")
    @Composable
    fun DeviceItem(device: BluetoothDevice) {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .padding(vertical = 4.dp)
        ) {
            Text(
                text = "Name: ${device.name ?: "Unknown"}",
                style = MaterialTheme.typography.bodyLarge
            )
            Text(
                text = "Address: ${device.address}",
                style = MaterialTheme.typography.bodyMedium
            )
        }
    }
}
